#pragma once
#include <windows.h>

#if defined(_UT) && !defined(CPUTCRT_EXPORTS)
#if _MSC_VER > 1400
#pragma comment(lib, "cputcrt9.lib")
#else
#pragma comment(lib, "cputcrt8.lib")
#endif
#endif

#ifdef CPUTCRT_EXPORTS
#define CPUTCRT_API __declspec(dllexport)
#else
#define CPUTCRT_API __declspec(dllimport)
#endif

class CUtTestBase {};

typedef void (CUtTestBase::*LPTestFunc)();

struct UtTestEntry
{
	LPTestFunc	lpFunc;
	LPCWSTR		lpName;
};

typedef void* (*LPMakeInstanceFunc)();
typedef void (*LPDestroyInstanceFunc)(void*);
typedef const UtTestEntry* (*LPGetTestsFunc)();

//Unit test entry point
CPUTCRT_API void LaunchUtSequence();

//Register an unit test class as a test group
CPUTCRT_API int RegisterUtGroup(LPMakeInstanceFunc fMakeInstance, LPDestroyInstanceFunc fDestroyInstance, LPGetTestsFunc fGetTests, LPCWSTR lpName);

#define DECLARE_UT_FUNC_TABLE \
	static void* MakeInstance(); \
	static void DestroyInstance(void* p); \
	static const UtTestEntry* GetTestsFunc(); \
	static int GroupId; \


#define BEGIN_UT_FUNC_TABLE(UtClass) \
	int UtClass::GroupId = RegisterUtGroup(&UtClass::MakeInstance, &UtClass::DestroyInstance, &UtClass::GetTestsFunc, L#UtClass); \
	void* UtClass::MakeInstance() { return new UtClass(); } \
	void UtClass::DestroyInstance(void* p) { delete (UtClass*)p; } \
__pragma (warning(push)) \
__pragma (warning(disable: 4407)) \
	const UtTestEntry* UtClass::GetTestsFunc() { \
		typedef UtClass theUtClass; \
		static const UtTestEntry _aTestFuncs[] = {


#define UT_FUNC_ENTRY(UtFunc) {(LPTestFunc)(&theUtClass::UtFunc), L#UtFunc},


#define END_UT_FUNC_TABLE 	NULL, NULL }; return _aTestFuncs; }; \
__pragma (warning(pop))
